package jp.syuriken.snsw.terenaibot.mal.twitter;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;

import jp.syuriken.snsw.terenaibot.WrapperException2;
import jp.syuriken.snsw.utils.CausedBySelective;
import twitter4j.RateLimitStatus;
import twitter4j.TwitterException;

/**
 * {@link TwitterPostWrapper}用の例外
 * 
 * @author $Author: snswinhaiku.lo@gmail.com $
 */
@SuppressWarnings("serial")
public class TwitterWrapperException extends WrapperException2 implements CausedBySelective {
	
	private static String n(String obj) {
		return obj == null ? "" : obj;
	}
	

	private TwitterException twitterException;
	
	private String postString;
	

	/**
	 * インスタンスを生成する。
	 * 
	 * @param twitterException twitterException
	 */
	public TwitterWrapperException(TwitterException twitterException) {
		super(twitterException);
		if (twitterException.exceededRateLimitation()) {
			setErrorReason(ErrorReason.EXCEED_API_LIMITATION);
		} else if (twitterException.isCausedByNetworkIssue()) {
			setErrorReason(ErrorReason.NETWORK_ISSUE);
		} else if (twitterException.isErrorMessageAvailable()) {
			if ("User is over daily status update limit.".equals(twitterException.getErrorMessage())) {
				setErrorReason(ErrorReason.OVER_POST_LIMITATION);
			} else if ("Status is a duplicate.".equals(twitterException.getErrorMessage())) {
				setErrorReason(ErrorReason.DUPLICATE);
			} else if ("Status is over 140 characters.".equals(twitterException.getErrorMessage())) {
				setErrorReason(ErrorReason.TOO_LONG);
			}
		}
		if (getErrorReason() == ErrorReason.UNKNOWN) {
			switch (twitterException.getStatusCode()) {
				case TwitterException.SERVICE_UNAVAILABLE: //503
					setErrorReason(ErrorReason.SERVICE_UNAVAILABLE);
					break;
				case TwitterException.INTERNAL_SERVER_ERROR:
					setErrorReason(ErrorReason.INTERNAL_SERVER_ERROR);
					break;
				case TwitterException.NOT_FOUND:
					setErrorReason(ErrorReason.NOT_FOUND);
					break;
				case TwitterException.FORBIDDEN:
					setErrorReason(ErrorReason.FORBIDDEN);
					break;
				case TwitterException.TOO_LONG:
					setErrorReason(ErrorReason.TOO_LONG);
					break;
				case TwitterException.BAD_GATEWAY:
					setErrorReason(ErrorReason.BAD_GATEWAY);
					break;
				default:
					setErrorReason(ErrorReason.UNKNOWN);
					break;
			}
		}
		this.twitterException = twitterException;
	}
	
	/**
	 * インスタンスを生成する。
	 * 
	 * @param twitterException TwitterException
	 * @param postString ポストした文字列
	 */
	public TwitterWrapperException(TwitterException twitterException, String postString) {
		this(twitterException);
		setPostString(postString);
	}
	
	@Override
	public boolean doLogCausedBy() {
		return false;
	}
	
	@Override
	public String getErrorDescription() {
		return twitterException.getErrorMessage();
	}
	
	@Override
	public String getErrorName() {
		return twitterException.isErrorMessageAvailable() ? twitterException.getErrorMessage() : "";
	}
	
	@Override
	public String getLocalizedMessage() {
		/**
		 * {0}: errorReason.toString()
		 * {1}: getStatusCode()
		 * {2}: getErrorName() (if available)
		 * {3}: getErrorDescription()
		 * {4}: (RateLimitStatus: "remain"/"all";reset "resetDate")
		 * {5}: getRequestPath()
		 * {6}: getPostString() (if available)
		 */
		String formatString;
		switch (getErrorReason()) {
			case EXCEED_API_LIMITATION:
			case OVER_POST_LIMITATION:
				formatString = "{0} ({1}): {2}";
				break;
			case TOO_LONG:
			case DUPLICATE:
				formatString = "{0} ({2}): {5}, posted=\"{6}\"";
				break;
			case SERVICE_UNAVAILABLE:
			case INTERNAL_SERVER_ERROR:
				formatString = "{0} (stcode={1}): {5}";
				break;
			case UNKNOWN:
			case NETWORK_ISSUE:
			case NOT_FOUND:
			case FORBIDDEN:
			case BAD_GATEWAY:
			default:
				formatString = "{0} (stcode={1}, error={2}): {5}";
				break;
		}
		RateLimitStatus rateLimitStatus = twitterException.getRateLimitStatus();
		SimpleDateFormat dateFormat = new SimpleDateFormat("H:m:s");
		String resetTimeString = "";
		String rateLimit;
		if (rateLimitStatus != null) {
			resetTimeString = dateFormat.format(rateLimitStatus.getResetTime());
			rateLimit =
					String.format("%s/%s; reset %s", rateLimitStatus.getRemainingHits(),
							rateLimitStatus.getHourlyLimit(), resetTimeString);
		} else {
			rateLimit = "null";
		}
		return MessageFormat.format(formatString, getErrorReason().toString(), getStatusCode(), n(getErrorName()),
				getErrorDescription(), rateLimit, twitterException.getRequestPath(), getPostString());
	}
	
	/**
	 * ポストしようとした文字列。ポスト時の例外ではない場合、nullが返ります。
	 * 
	 * @return the postString
	 */
	public String getPostString() {
		return postString;
	}
	
	@Override
	public RateLimitStatus getRateLimitStatus() {
		return twitterException.getRateLimitStatus();
	}
	
	@Override
	public int getStatusCode() {
		return twitterException.getStatusCode();
	}
	
	/**
	 * ポスト文字列を設定する。
	 * 
	 * @param postString the postString to set
	 */
	public void setPostString(String postString) {
		this.postString = postString;
	}
}
